/*
 * XMLMapDialog.java
 * Created on 28. Mai 2005
 * Modified on 31. March 2009
 * CVS: $Id$
 * Last Modify: $Date: $
 */

package com.tcmj.common.swing.dialog.xmlmap;

import com.tcmj.common.tools.xml.map.XMLMap;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.util.Iterator;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTable;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
import static com.tcmj.common.swing.dialog.xmlmap.XMLMapDialog.SaveMode.*;



/**
 * Dialog to display and edit entries of XMLMap.
 * 
 * @author Thomas Deutsch - thomas-deutsch@tcmj.de
 * @JUnit Test available!
 */
public class XMLMapDialog extends javax.swing.JDialog {

    /**
     * @return the saveMode
     */
    public SaveMode getSaveMode() {
        return saveMode;
    }

    /**
     * @param saveMode the saveMode to set
     */
    public void setSaveMode(SaveMode saveMode) {
        this.saveMode = saveMode;
    }


    public enum SaveMode {SAVE_TO_MAP_AND_FILE, SAVE_TO_MAP_ONLY};

    private SaveMode saveMode = SAVE_TO_MAP_AND_FILE;


    /** Map implementation for the XML-File. */
    private XMLMap model;


    private boolean changed = false;

    /**
     * Option to activate the question to save before closing
     */
    private boolean activatesavestatus = false;


    /**
     * Creates new form XMLMapDialog.
     * @param parent parent frame
     * @param modal yes or no
     */
    public XMLMapDialog(java.awt.Frame parent, boolean modal) {
        super(parent, modal);
        initComponents();

        this.tblData.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
    }

    /**
     * Activate or Deactivate the Question if changes were unsaved.<br>
     * Default this setting is not activated.
     *
     * @param value true to activate, false to deactivate.
     */
    public void setQuestionIfUnsaved(boolean value) {
        this.activatesavestatus = value;
    }


    /**
     * Set the data model with the XML-Entries to display.
     *
     * @param model XMLPropertyModel
     */
    public void setDataModel(XMLMap model) {

        this.model = model;

        XMLMapTableModel tmodel = new XMLMapTableModel(model);
        this.tblData.setModel(tmodel);

        tmodel.addTableModelListener(listener = new XMLMapTableModelListener(changed));

        // Install the custom renderer on the first visible column
        int vColIndex = 0;
        TableColumn col = tblData.getColumnModel().getColumn(vColIndex);
        col.setCellRenderer(new XMLMapTableCellRenderer());
    }

    XMLMapTableModelListener listener;

    /**
     * This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        pnHeader = new javax.swing.JPanel();
        scpnBody = new javax.swing.JScrollPane();
        tblData = new javax.swing.JTable();
        pnBody = new javax.swing.JPanel();
        lblTitle = new javax.swing.JLabel();
        pnActions = new javax.swing.JPanel();
        btnSave = new javax.swing.JButton();
        btnClose = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);

        pnHeader.setLayout(new java.awt.BorderLayout());

        tblData.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null}
            },
            new String [] {
                "Title 1", "Title 2", "Title 3", "Title 4"
            }
        ));
        scpnBody.setViewportView(tblData);

        pnHeader.add(scpnBody, java.awt.BorderLayout.CENTER);

        getContentPane().add(pnHeader, java.awt.BorderLayout.CENTER);

        lblTitle.setText("XML Properties");
        pnBody.add(lblTitle);

        getContentPane().add(pnBody, java.awt.BorderLayout.NORTH);

        btnSave.setText("save");
        btnSave.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnSaveActionPerformed(evt);
            }
        });
        pnActions.add(btnSave);

        btnClose.setText("close");
        btnClose.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnCloseActionPerformed(evt);
            }
        });
        pnActions.add(btnClose);

        getContentPane().add(pnActions, java.awt.BorderLayout.SOUTH);

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void btnCloseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCloseActionPerformed
        if (listener.getStatus() == true && this.activatesavestatus == true) {
            String msg = "<html>Changes are currently not saved!<br>Do you really want to close?</html>";
            int returnvalue = JOptionPane.showConfirmDialog(this, msg, "Warning!", JOptionPane.YES_NO_OPTION);
            if (returnvalue == JOptionPane.YES_OPTION) {
                this.dispose();
            } else {
            }

        } else {
            this.dispose();
        }


    }//GEN-LAST:event_btnCloseActionPerformed

    private void btnSaveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnSaveActionPerformed


        TableModel tmod = tblData.getModel();

        int maxrows = tmod.getRowCount();

        for (int i = 0; i < maxrows; i++) {

            String name = (String) tmod.getValueAt(i, 0);
            String value = (String) tmod.getValueAt(i, 1);

//            System.out.println("N: "+name+" V: "+value);

//            int sep = name.indexOf(XMLPropertyModel.SEP);
//            String group = name.substring(0,sep);
//            String key = name.substring(sep+1);
////            System.out.println("group "+group+" key "+key);

            try {

                this.model.put(name, value);

            } catch (Exception ex) {
                System.out.println("Errare Computer Est: " + ex.getMessage());
            }

        }

        try {
            if (SAVE_TO_MAP_AND_FILE==getSaveMode()) {
                System.out.println("save to "+this.model.getXMLFileHandle().getPath() );
                this.model.saveXML();
            }
            
            
        } catch (Exception ex) {
            System.out.println("Error saving XML Property File: " + ex.getMessage());
        }
listener.resetStatus();

    }//GEN-LAST:event_btnSaveActionPerformed

    class XMLMapTableModelListener implements TableModelListener {

        boolean changed;

        public XMLMapTableModelListener(boolean b) {
            this.changed = b;
        }

        public void tableChanged(javax.swing.event.TableModelEvent e) {
            System.out.println("tableChanged");
            this.changed = true;
        }

        public boolean getStatus() {
            return this.changed;
        }

        public void resetStatus() {
            this.changed = false;
        }
    }


    class XMLMapTableModel extends DefaultTableModel {

        XMLMap xmlmodel;

        public XMLMapTableModel(XMLMap model) {

            this.xmlmodel = model;

            int size = model.size();

            String[][] rowdata = new String[size][2];

            Iterator itcol = model.entrySet().iterator();
            for (int i = 0; itcol.hasNext(); i++) {

//                XMLPropertyEntry ent = (XMLPropertyEntry)itcol.next();

                XMLMap.Entry ent = (XMLMap.Entry) itcol.next();

                String column1 = (String)ent.getKey();
                String column2 = (String)ent.getValue();

                rowdata[i][0] = column1;
                rowdata[i][1] = column2;
            }

            String[] columnnames = new String[]{"Property", "Value"};

            setDataVector(rowdata, columnnames);

        }


        @Override
        public int getRowCount() {
            return model.size();
        }

        @Override
        public int getColumnCount() {
            return 2;
        }

        @Override
        public boolean isCellEditable(int row, int column) {

            if (column == 0) {
                return false;
            } else {
                return true;
            }
        }
    }



    // This renderer extends a component. It is used each time a
    // cell must be displayed.

    public class XMLMapTableCellRenderer extends JLabel implements TableCellRenderer {

        // This method is called each time a cell in a column
        // using this renderer needs to be rendered.
        public Component getTableCellRendererComponent(JTable table, Object value,
                                                       boolean isSelected, boolean hasFocus, int rowIndex, int vColIndex) {
            // 'value' is value contained in the cell located at
            // (rowIndex, vColIndex)
            setBackground(Color.LIGHT_GRAY);
            setOpaque(true);

            if (isSelected) {
                // cell (and perhaps other cells) are selected
            }

            if (hasFocus) {
                // this cell is the anchor and the table has the focus
            }

            // Configure the component with the specified value
            setText(value.toString());

            XMLMapTableModel model = (XMLMapTableModel) table.getModel();
            Object obj = model.xmlmodel.getObject(String.valueOf(value));
            if (obj != null) {
                setToolTipText(String.valueOf(obj.getClass()));
            } else {
                setToolTipText("");
            }

            // Since the renderer is a component, return itself
            return this;
        }

        // The following methods override the defaults for performance reasons
        @Override
        public void validate() {
        }

        @Override
        public void revalidate() {
        }

        @Override
        protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
        }

        @Override
        public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) {
        }
    }


    //
    /**
     * Shows the Dialog.
     * Can only be used if a XMLPropertyModel was set.
     *
     * @throws java.lang.NullPointerException if no model was set or the model
     *                                        has no Entries.
     */
    public void show() throws NullPointerException {

        //determine the size of the screen:
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();

        if (this.model == null || this.model.size() == 0) {
            throw new NullPointerException("XMLMap was not set or has no Entries!");
        } else {

            int w = 400;
            //each record needs 16 pixel space (+titel and buttons)
            int h = 125 + this.model.size() * 16;

            //if the screen size is too small use sliders
            if (h > screenSize.height) {
                h = screenSize.height - 200;
            }
            int x = (screenSize.width - w) / 2;
            int y = (screenSize.height - h) / 2;

            setBounds(x, y, w, h);
            super.show();
        }
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btnClose;
    private javax.swing.JButton btnSave;
    private javax.swing.JLabel lblTitle;
    private javax.swing.JPanel pnActions;
    private javax.swing.JPanel pnBody;
    private javax.swing.JPanel pnHeader;
    private javax.swing.JScrollPane scpnBody;
    private javax.swing.JTable tblData;
    // End of variables declaration//GEN-END:variables

}
